"use strict";
const path = require("path");
const pkgDir = require("pkg-dir").sync;
const fse = require("fs-extra");
const npminstall = require("npminstall");
const pathExists = require("path-exists").sync;

const { isObject } = require("@akimixu-cli-dev/utils");
const formatPath = require("@akimixu-cli-dev/format-path");
const {
  getDefaultRegistry,
  getNpmLatestVersion,
} = require("@akimixu-cli-dev/get-npm-info");

// 这是一个package类，用于获取package的信息
class Package {
  constructor(options) {
    if (!options) {
      throw new Error("Package类的options参数不能为空!");
    }
    if (!isObject(options)) {
      throw new Error("Package类的options参数必须为对象!");
    }
    // package的入口文件路径
    this.targetPath = options.targetPath;
    // package的缓存路径
    this.storeDir = options.storeDir;
    // package的name
    this.packageName = options.packageName;
    // package的version
    this.packageVersion = options.packageVersion;
    // package的缓存目录前缀
    this.cacheFilePathPrefix = this.packageName; //新版本npminstall pkg-dir不用处理了
  }

  async prepare() {
    // 1.判断当前package是否存在
    if (this.storeDir && !pathExists(this.storeDir)) {
      fse.mkdirpSync(this.storeDir); // 创建缓存目录
    }

    // 将版本的latest转化为真实的版本号
    if (this.packageVersion === "latest") {
      this.packageVersion = await getNpmLatestVersion(this.packageName);
    }
    // 1.拼接出package的缓存路径
    // 例如课程上的是_@imooc-cli_init@1.1.2@@imooc-cli/
    // 实际路径是@imooc-cli/init  1.1.2
    // 以上的缓存路径时npminstall 4.10.0版本的缓存路径
    // 最新版本更新了不是这样写的了
  }
  // get cacheFilePath() {
  //   return path.resolve(
  //     this.storeDir,
  //     ".store",
  //     `${this.cacheFilePathPrefix}@${this.packageVersion}`
  //   );
  // }

  get cacheFilePath() {
    return path.resolve(this.storeDir, `${this.cacheFilePathPrefix}`);
  }

  // 拼写指定版本的缓存路径
  getSpecificCacheFilePath(packageVersion) {
    // return path.resolve(
    //   this.storeDir,
    //   ".store",
    //   `${this.cacheFilePathPrefix}@${packageVersion}`
    // );
    return path.resolve(this.storeDir, `${this.cacheFilePathPrefix}`);
  }
  // 判断package是否存在
  async exists() {
    // 1.判断当前文件是使用的缓存模式还是targetpath
    if (this.storeDir) {
      await this.prepare();
      return pathExists(this.cacheFilePath);
    } else {
      return pathExists(this.targetPath);
    }
  }
  // 安装package
  async install() {
    await this.prepare();
    return npminstall({
      root: this.targetPath, // 模块路径
      storeDir: this.storeDir, // 缓存路径
      registry: getDefaultRegistry(), // 源
      pkgs: [
        {
          name: this.packageName,
          version: this.packageVersion,
        },
      ],
    });
  }
  // 更新package
  async update() {
    await this.prepare();
    // 1.获取最新的npm模块版本号
    const latestPackageVersion = await getNpmLatestVersion(this.packageName);
    // 2.查询最新版本号对应的路径是否存在
    const latestFilePath = this.getSpecificCacheFilePath(latestPackageVersion);
    // 3.如果不存在，则直接安装最新版本
    if (!pathExists(latestFilePath)) {
      await npminstall({
        root: this.targetPath,
        storeDir: this.storeDir,
        registry: getDefaultRegistry(),
        pkgs: [
          {
            name: this.packageName,
            version: latestPackageVersion,
          },
        ],
      });
      this.packageVersion = latestPackageVersion;
    } else {
      this.packageVersion = latestPackageVersion;
    }
  }
  // 获取package的入口文件
  getRootFilePath() {
    function _getRootFile(targetPath) {
      // 1.获取package.json 所在的目录 有可能传进来的targetPath不是用户的主目录 - pkg-dir
      let dir = pkgDir(targetPath);
      if (dir) {
        // 2.读取package.json - require()
        const pkgFile = require(path.resolve(dir, "package.json"));
        // 3.main/lib - path
        if (pkgFile && pkgFile.main) {
          //4.路径的兼容（macos/windows）
          return formatPath(path.resolve(dir, pkgFile.main));
        }
      }
      return null;
    }
    if (this.storeDir) {
      console.log("shangmian");
      return _getRootFile(this.cacheFilePath);
    } else {
      return _getRootFile(this.targetPath);
    }
  }
  // 将最新版本号写入package.json
  setPkgVersion(version) {
    const pkgFile = this.packageJsonFile;
    pkgFile.version = version;
    fse.writeFileSync(this.packageJsonPath, JSON.stringify(pkgFile));
  }
}

module.exports = Package;
